package com.frontop.terminal.rmonclient.worker;


import com.frontop.terminal.rmonclient.compress.CompressUtil;
import com.frontop.terminal.rmonclient.graphic.Screenshot;
import com.frontop.terminal.rmonclient.protocol.Command;
import com.frontop.terminal.rmonclient.protocol.Packet;
import com.frontop.terminal.rmonclient.util.Log;

import java.util.Objects;

/**
 * @author matrixy
 * @date 2018/4/10
 */
public class CompressWorker extends BaseWorker {
    /**
     * 压缩方式
     */
    String compressMethod = "rle";

    /**
     * 上一屏的截屏，用于比较图像差
     */
    Screenshot lastScreen = null;
    int sequence = 0;

    public CompressWorker() {
        // do nothing here
    }


    private void compress() {
        Screenshot screenshot = null;
        while (ScreenImages.hasScreenshots()) {
            screenshot = ScreenImages.getScreenshot();
        }
        if (screenshot == null || screenshot.isExpired()) {
            return;
        }

        // 分辨率是否发生了变化？
        if (Objects.nonNull(lastScreen) && (lastScreen.width != screenshot.width || lastScreen.height != screenshot.height)) {
            lastScreen = null;
        }

        // 1. 求差
        int[] bitmap = new int[screenshot.bitmap.length];
        int changedColors = 0, start = -1, end;
        if (lastScreen != null) {
            for (int i = 0; i < bitmap.length; i++) {
                if (lastScreen.bitmap[i] == screenshot.bitmap[i]) {
                    bitmap[i] = 0;
                } else {
                    if (start == -1) {
                        start = i;
                    }
                    changedColors += 1;
                    bitmap[i] = screenshot.bitmap[i];
                }
            }
        } else {
            bitmap = screenshot.bitmap;
        }

        if (lastScreen != null && changedColors == 0) {
            return;
        }

        // 2. 压缩
        start = 0;
        end = bitmap.length;
        byte[] compressedData = CompressUtil.process(this.compressMethod, bitmap, start, end);


        // 3. 入队列
        Packet packet = Packet.create(Command.SCREENSHOT, compressedData.length + 16);
        packet.addShort((short) screenshot.width)
                .addShort((short) screenshot.height)
                .addLong(screenshot.captureTime)
                .addInt(sequence++);
        packet.addBytes(compressedData);
        ScreenImages.addCompressedScreen(packet);

        lastScreen = screenshot;
    }

    @Override
    public void run() {
        while (!this.isTerminated()) {
            try {
                compress();
                sleep(100);
            } catch (Exception e) {
                Log.error(e);
            }
        }
    }
}
